#ifndef LIST_H
#define LIST_H

#include<stdio.h>
#include<string.h>
#include<conio.h>
#include<stdlib.h>
#include<assert.h>
#include<io.h>

//Number of Hash keys:
#define Num_of_hash 100

//Defining the type of an element:
struct List_Element
{
    char *value;
    struct List_Element *prev;
    struct List_Element *next;
};

struct Key_Element
{
    int key;
    int num_of_elem;
    struct List_Element *first;
};

struct Key_Element Array_Of_Keys[Num_of_hash] = {};



void Element_Insert(struct List_Element*, char*);
void Element_Delete(struct List_Element*);
void List_Display(struct List_Element*);
void Element_Display(struct List_Element*);
int Sorting_Function(char*, int);





//---------------------------------------------------------------------
//Inserting the element into a hash table (Relevant to this task, not the common solution)
void List_Insert(char *line, int option)
{

    struct List_Element *NewElement, *Temporary;                       //New Elements (Initialized later)
    int key = 0;
    key=Sorting_Function(line,option);                                 //Getting the key for the word
    assert(key<=Num_of_hash);                                          //Chekcking the key
    assert(key>=0);
    NewElement=(struct List_Element *)calloc(1,sizeof(struct List_Element));
    NewElement->next=NULL;
    NewElement->prev=NULL;
    NewElement->value=line;
    if (Array_Of_Keys[key].first==NULL)
    {
        Array_Of_Keys[key].first=NewElement;
        Array_Of_Keys[key].num_of_elem++;
    }
    else
    {
        Temporary=Array_Of_Keys[key].first;
        if (strcmp(NewElement->value,Temporary->value)<0)
        {
            Array_Of_Keys[key].first = NewElement;
            NewElement->next=Temporary;
            Temporary->prev=NewElement;
            Array_Of_Keys[key].num_of_elem++;
        }
        else
        {
            while (((strcmp(NewElement->value,Temporary->value))<0)&&(Temporary->next!=NULL))
            {
                Temporary=Temporary->next;
            }
            if (Temporary->next==NULL)
            {
                Temporary->next=NewElement;
                NewElement->prev=Temporary;
                Array_Of_Keys[key].num_of_elem++;
            }
            else
            {
                Temporary->next->prev=NewElement;
                NewElement->next=Temporary->next;
                Temporary->next=NewElement;
                NewElement->prev=Temporary;
                Array_Of_Keys[key].num_of_elem++;
            }


        }
    }

}
//---------------------------------------------------------------------
//Checking the sorting option
int Check_Sorting_Option(int value)
{
    if ((value<1)||(value>5))
        return 0;
    else
        return 1;
}
//---------------------------------------------------------------------
//Asking User to type in a sorting function
int Interface()
{
    int option;
    printf("|=================================|\n");
    printf("|     Options to choose from      |\n");
    printf("|---------------------------------|\n");
    printf("| 1.Returning 0                   |\n");
    printf("| 2.First letter                  |\n");
    printf("| 3.Length of the word            |\n");
    printf("| 4.Summ of the ASCII symbols     |\n");
    printf("| 5.Moving the pointer            |\n");
    printf("|=================================|\n");
    printf("What sorting option do you choose? \n");
    printf("Answer:  ");
    while ((option<1)||(option>5))
    {
        scanf("%i", &option);
        if (Check_Sorting_Option(option)==1)
            break;
        else
            printf("I have only 5 options to choose from. Make your choice again  ");
    }
    return option;
}
//---------------------------------------------------------------------
void Filling_The_array_of_keys()
{
    int counter;
    for(counter = 0; counter < Num_of_hash; counter++)
    {
        Array_Of_Keys[counter].key = counter;
        Array_Of_Keys[counter].first = NULL;
        Array_Of_Keys[counter].num_of_elem = 0;
    }
}

//*******************************************************************
//The sorting function itself
int Sorting_Function(char *Material_To_Sort, int option)
{
    int sum = 0, counter = 0, length = 0;
    switch (option)
    {
        case 1: return 0;
        case 2: if (Material_To_Sort[0]<Num_of_hash)
                return Material_To_Sort[0];
                else
                    return Material_To_Sort[0]%Num_of_hash;
        case 3: if (strlen(Material_To_Sort)<Num_of_hash)
                    return strlen(Material_To_Sort);
                else
                    return strlen(Material_To_Sort)%Num_of_hash;
        case 4:
        {
            counter = 0;
            length=strlen(Material_To_Sort);
            while (counter<length)
            {
                    sum = sum + Material_To_Sort[counter];
                    counter++;
            }
            return sum%Num_of_hash;
        };
        case 5:
        {
            return 0;
        }
    }
}
//---------------------------------------------------------------------

/*void List_Delete()
{
    struct List_Element *Temporary,*Temporary2;
    int i=0;
    for(Temporary=Top;Temporary!=NULL;Temporary=Temporary->link)
    {
        i++;
    }
    if(i==0)
    {
        printf("Underflow");
        getch();
    }
    else
    {
        Temporary2=Top->link;
        Top=Temporary2;
        free(Temporary2);
        printf("\n***The value has been poped***\n");
    }
}

void List_Print_Till_The_End()
    {
    struct List_Element *Temporary;
    printf("\n****Stack Values****\n");
    for(Temporary = Top; Temporary != NULL; Temporary = Temporary->link)
       {
       printf("%d\n",Temporary->value);
       }
    getch();
    }

void Stack_Peep()
    {
    struct stack *Temporary;
    int Position,i=0,j=0;
    printf("Please enter the position number: ");
    scanf("%d",&Position);
    for(Temporary=Top;Temporary!=NULL;Temporary=Temporary->link)
     {
     i++;
     }
    if(Position>i)
       {
       printf("\n Over Limit\n");
       getch();
       }
     else
       {
       Temporary=Top;
       for(j=0;j<Position-1;j++)
           {
          Temporary=Temporary->link;
           }
        printf("\nThe value of position %d is :%d",Position,Temporary->value);
        getch();
       }
    }

void Stack_Change()
{
    struct stack *Temporary,*NewElement;
    int Position,i=0,j=0;
    printf("Please enter the position number: ");
    scanf("%d",&Position);
    for(Temporary=Top;Temporary!=NULL;Temporary=Temporary->link)
     {
     i++;
     }
    if(Position>i)
       {
       printf("\n Over Limit \n");
       getch();
       }
     else
       {
       NewElement=(struct stack *)malloc(sizeof(struct stack));
       printf("Enter value for stack: ");
       scanf("%d",&NewElement->value);
       Temporary=Top;
       for(j=0;j<Position-1;j++)
           {
          Temporary=Temporary->link;
           }
        Temporary->value=NewElement->value;
        }
}



//------------------------Working with the sStack elements--------------------

void Stack_Add()
{
    struct stack *Second,*First;
    First=Top;
    Second=First->link;
    Second->value=Second->value+First->value;
    Top=Second;

}

void Stack_Sub()
{
    struct stack *Second,*First;
    First=Top;
    Second=First->link;
    Second->value=Second->value-First->value;
    Top=Second;

}

void Stack_Mul()
{
    struct stack *Second,*First;
    First=Top;
    Second=First->link;
    Second->value=Second->value*First->value;
    Top=Second;

}

void Stack_Div()
{
    struct stack *Second,*First;
    First=Top;
    Second=First->link;
    assert(First->value!=0);
    Second->value=Second->value/First->value;
    Top=Second;

}

void Factorial(int num)
{
    int i;
    struct stack *First;
    Second->link=NULL;
    Second->value=1;
    First->link=Third;
    First->value=1;
    for (i=0;i<num-2;i++)
    {
        First=(struct stack *)calloc(1,sizeof(struct stack));
        First->value=Top->value+Top->link->value;
        First->link=Top;
        Top=First;
    }
}

//----------------------Working with the Stack elements --------------------

//****************************************************************
/*void Def_File_Address(char* key, char* code)
{
    int i = 0, success = 0;
    printf("Choose the option: \n");
    printf("1. Stack_key has an adress <C:/Users/Andrey/Desktop/MIPT/IT/Class/Programs/Homeworks/Stack_key.txt> \n Stack_code has an adress <C:/Users/Andrey/Desktop/MIPT/IT/Class/Programs/Homeworks/Stack_code.txt>\n");
    printf("2.Address is different. \n");
    scanf("%i", &i);
    while (success!=1)
    {if (i==1)
    {
        key="C:/Users/Andrey/Desktop/MIPT/IT/Class/Programs/Homeworks/Stack_key.txt";
        code="C:/Users/Andrey/Desktop/MIPT/IT/Class/Programs/Homeworks/Stack_code.txt";
        success = 1;
    }
    else
    {
        printf("Enter the adress of both key and code files");
        scanf("%s",key);
        scanf("%s", code);
        success = 1;
    }
    if ((i!=1)&&(i!=2))
        printf("Check the option! ");
    }
}*/




/*void File_transform() //creates new files
{
    Def_File_Address(Address_key, Address_code);
    char *Address_key = "C:/Users/Andrey/Desktop/MIPT/IT/Class/Programs/Homeworks/Stack_key.txt",
         *Address_code = "C:/Users/Andrey/Desktop/MIPT/IT/Class/Programs/Homeworks/Stack_code.txt",
         *Buffer = "C:/Users/Andrey/Desktop/MIPT/IT/Class/Programs/Homeworks/Buffer.txt",
         symbol;
    int Num_of_operations = 0;
    FILE *f_key=fopen(Address_key,"r"), *f_code = fopen(Address_code,"");
    int len=filelength(fileno(f_key));
    while ((symbol=fgetc(f_key))!=EOF)
    {
        if (symbol=='\n')
            Num_of_operations++;

    }
    printf("%i", Num_of_operations);



}


//**********************************************************
void Stack_From_File()
{
    File_transform();
};
*/

#endif // LIST_H
